package com.hlf.modules.api.service.impl;

import com.hlf.common.constants.Constants;
import com.hlf.common.exception.BusinessException;
import com.hlf.common.utils.*;
import com.hlf.modules.api.entity.BusinessKind;
import com.hlf.modules.api.entity.CheckCodeCount;
import com.hlf.modules.api.entity.Checkcode;
import com.hlf.modules.api.mapper.BusinessKindMapper;
import com.hlf.modules.api.mapper.CheckCodeCountMapper;
import com.hlf.modules.api.service.CheckcodeService;
import com.hlf.modules.api.service.SMSService;
import com.hlf.modules.sys.service.SysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

/**
 * 短信服务层接口实现类
 */
@Service
public class SMSServiceImpl implements SMSService {

    private static final Logger logger = LoggerFactory.getLogger(SMSServiceImpl.class);

    @Autowired
    CheckcodeService checkcodeService;
    @Autowired
    SysUserService sysUserService;
    @Autowired
    private BusinessKindMapper businessKindMapper;
    @Autowired
    private CheckCodeCountMapper checkCodeCountMapper;
    @Autowired
    PropertieUtil propertieUtil;

    /**
     * 短信计数
     *
     * @param mobile
     * @param messageType
     */
    public void sendCount(String mobile, Byte messageType) {
        //计数
        CheckCodeCount checkCodeCount = checkCodeCountMapper.selectByPhoneAndBizType(mobile, messageType);
        if (checkCodeCount == null) {
            checkCodeCount = new CheckCodeCount();
            checkCodeCount.setId(IdWorkerFactory.nextId());
            checkCodeCount.setMobilePhone(mobile);
            checkCodeCount.setCountType((byte) 1);
            checkCodeCount.setBizType(messageType);
            checkCodeCount.setCount(1);
            Date date = new Date();
            checkCodeCount.setDate(date);
            checkCodeCount.setInsertDate(date);
            checkCodeCount.setLastUpdateDate(date);
            checkCodeCountMapper.insert(checkCodeCount);
        } else {
            LocalDate day = LocalDate.now();
            Date date = checkCodeCount.getDate();
            Instant instant = date.toInstant();
            ZoneId zoneId = ZoneId.systemDefault();
            // atZone()方法返回在指定时区从此Instant生成的ZonedDateTime。
            LocalDate localDate = instant.atZone(zoneId).toLocalDate();
            boolean equals = day.equals(localDate);
            //当天
            if (equals) {
                Integer count = checkCodeCount.getCount();
                if (count > Integer.valueOf(propertieUtil.getPropertie("ADAY_UPDATE_PWD_NUM"))) {
                    throw new BusinessException("您在一天之内获取验证码已经超过允许次数!");
                }
                checkCodeCount.setCount(checkCodeCount.getCount() + 1);
                checkCodeCountMapper.updateByPrimaryKeySelective(checkCodeCount);
            } else {
                //非当天
                checkCodeCount.setCount(1);
                checkCodeCount.setDate(new Date());
                checkCodeCountMapper.updateByPrimaryKeySelective(checkCodeCount);
            }
        }
    }

    @Override
    public void sendMoblieVCode(String mobile, Integer codType, int userType) {
        boolean isMobile = ValidateUtils.isMobileNO(mobile);
        boolean mobileExist = sysUserService.mobileCount(mobile) > 0;
        if (isMobile) {
            if (Constants.MESSAGE_TYPE_REGISTER == codType) {//只针对注册
                if (!mobileExist) {
                    this.getMoblieVCode(mobile, codType);
                } else {
                    throw new BusinessException("手机号码已被注册!");
                }
            } else {
                //如果不是注册,计数
                if (!mobileExist) {
                    throw new BusinessException("该手机号码未注册!");
                }
                sendCount(mobile, codType.byteValue());
                this.getMoblieVCode(mobile, codType);
            }
        } else {
            throw new BusinessException("手机号码校验失败!");
        }
    }

    @Override
    public void getMoblieVCode(String mobile, Integer codeType) {
        if ("ALDY".equals(SmsConstants.SMS_GALLERY)) {
            sendMsgByALDY(mobile, codeType);
        } else if ("UMS".equals(SmsConstants.SMS_GALLERY)) {
            sendMsgByUMS(mobile, codeType);
        } else {
            sendMsgByCSMD(mobile, codeType);
        }
    }

    /**
     * 校验验证码是否正确
     */
    @Override
    public boolean checkAuthCode(String mobile, String code, int codeType) {
        Checkcode checkcode = checkcodeService.findNearestCode(mobile, code, codeType);
        if (checkcode != null) {
            // 验证码有效时间,单位毫秒
            int validTime = Integer.valueOf(propertieUtil
                    .getPropertie("FORGET_PWD_VALID_TIME")) * 60 * 1000;
            Date now = new Date();
            long time = now.getTime() - checkcode.getCodSendTime().getTime();
            if (time > validTime) {
                logger.error("校验短信验证码,验证码已失效。");
                throw new BusinessException("验证码已失效");
            } else if (Constants.COD_USED_YES == checkcode.getCodUsed()) {
                logger.error("校验短信验证码,验证码已被使用。");
                throw new BusinessException("验证码已被使用");
            } else {
                // 改变验证码状态为已使用
                checkcodeService.changeCodeUsed(checkcode.getCodId());
            }
        } else {
            logger.error("校验短信验证码,验证码不正确。");
            throw new BusinessException("验证码不正确");
        }
        return true;
    }


    //创世漫道短信通道
    private void sendMsgByCSMD(String mobile, Integer codType) {
        logger.info("发送短信类型{}", codType);
        String code;
        // 开发模式验证码使用默认验证码
        if (Constants.MODE_TYPE_DEV.equals(Constants.MODE_TYPE)) {
            code = SmsConstants.DEFAULT_VERIFICATION_CODE_6;
            logger.debug("开发环境请使用默认验证码{}验证", code);
        } else {
            code = (int) ((Math.random() * 9 + 1) * 100000) + "";
        }
        String content = "";
        int validTime = Integer.valueOf(propertieUtil.getPropertie("FORGET_PWD_VALID_TIME"));
        if (SmsConstants.CODE_MERCHANT_REGISTER == codType) {
            content = propertieUtil.getPropertie("MERCHANT_REGISTER_CONTENT");
        } else if (SmsConstants.CODE_PERSONAL_REGISTER == codType) {
            content = propertieUtil.getPropertie("PERSONAL_REGISTER_CONTENT");
        } else if (SmsConstants.CODE_MERCHANT_BONUS_ENCHASHMENT == codType) {
            content = propertieUtil.getPropertie("BONUS_ENCHASHMENT_CONTENT");
        } else if (SmsConstants.CODE_MERCHANT_BIND_TONGGUANG == codType) {
            content = propertieUtil.getPropertie("BIND_TONGGUANG_CONTENT");
        } else if (SmsConstants.CODE_STOREMANAGER_BIND_POS == codType) {
            content = propertieUtil.getPropertie("BIND_POS_CONTENT");
        } else {
            throw new BusinessException("发送短信类型异常");
        }
        content = MessageFormat.format(content, code, validTime);
        boolean sendResult = true;
        // 非开发模式才发送短信验证码
        if (!Constants.MODE_TYPE_DEV.equals(Constants.MODE_TYPE)) {
            sendResult = SMSUtil.getInstance().sendSMSToMobile(mobile, content);
        }
        if (sendResult) {
            Checkcode checkcode = new Checkcode();
            checkcode.setCodType(codType);
            checkcode.setCodMobile(mobile);
            checkcode.setCodCode(code);
            checkcode.setCodUsed(Constants.COD_USED_NO);
            checkcode.setCodSendTime(new Date());
            checkcodeService.insert(checkcode);
        }
    }

    //阿里大于短信通道
    private void sendMsgByALDY(String mobile, Integer codType) {
        logger.info("阿里大于短信通道，发送短信类型{}", codType);
        String code;
        // 开发模式验证码使用默认验证码
        if (Constants.MODE_TYPE_DEV.equals(Constants.MODE_TYPE)) {
            code = SmsConstants.DEFAULT_VERIFICATION_CODE_6;
            logger.debug("开发环境请使用默认验证码{}验证", code);
        } else {
            code = (int) ((Math.random() * 9 + 1) * 100000) + "";
        }

        int validTime = Integer.valueOf(propertieUtil.getPropertie("FORGET_PWD_VALID_TIME"));
        String templateCode = "";
        if (SmsConstants.CODE_MERCHANT_REGISTER == codType) {
            templateCode = SmsConstants.ALDY_SMS_TEMPLATE_REGISTER;
        } else if (SmsConstants.CODE_PERSONAL_REGISTER == codType) {
            templateCode = SmsConstants.ALDY_SMS_TEMPLATE_BIND;
        } else if (SmsConstants.CODE_MERCHANT_BONUS_ENCHASHMENT == codType) {
            templateCode = SmsConstants.ALDY_SMS_TEMPLATE_BONUS;
        } else if (SmsConstants.CODE_MERCHANT_FILL_INFO == codType) {
            templateCode = SmsConstants.ALDY_SMS_TEMPLATE_FILL;
        } else if (SmsConstants.CODE_MERCHANT_BIND_TONGGUANG == codType) {
            templateCode = SmsConstants.ALDY_SMS_TEMPLATE_BIND_TONGGUANG;
        } else if (SmsConstants.CODE_STOREMANAGER_BIND_POS == codType) {
            templateCode = SmsConstants.ALDY_SMS_TEMPLATE_BIND_POS;
        } else {
            throw new BusinessException("发送短信类型异常");
        }
        logger.info("阿里大于短信通道，发送短信模板{}", templateCode);
        boolean sendResult = true;
        String paramJosn = "{\"code\":\"" + code + "\",\"time\":\"" + validTime + "\"}";
        // 非开发模式才发送短信验证码
        if (!Constants.MODE_TYPE_DEV.equals(Constants.MODE_TYPE)) {
            //阿里大于短信通道，一分钟之内对同一手机号码发短信会有异常
            int res = checkcodeService.getDifftimeByNow(mobile);
            logger.info("阿里大于发送短信模板(时间差：秒){}", res);
            if (res >= 60) {
                boolean timesLimit = checkcodeService.getCodIdByNowAndLimitCount(mobile, 4, 1);
                if (!timesLimit) {
                    boolean timesLimit2 = checkcodeService.getCodIdByNowAndLimitCount(mobile, 9, 24);
                    if (!timesLimit2) {
                        sendResult = SMSUtil.getInstance().sendMsgALDY(templateCode, mobile, paramJosn);
                    } else {
                        logger.error("阿里大于发送短信模板,超过一天允许数。{}", mobile);
                        throw new BusinessException("您在一天之内获取验证码已经超过允许次数。");
                    }
                } else {
                    logger.error("阿里大于发送短信模板,超过一小时允许数。{}", mobile);
                    throw new BusinessException("您在一小时之内获取验证码已经超过允许次数。");
                }
            } else {
                logger.error("阿里大于发送短信模板,一分钟之内多次获取。{}", mobile);
                throw new BusinessException("请勿频繁操作，" + (60 - res) + "秒后再获取验证码。");
            }
        }
        if (sendResult) {
            Checkcode checkcode = new Checkcode();
            checkcode.setCodType(codType);
            checkcode.setCodMobile(mobile);
            checkcode.setCodCode(code);
            checkcode.setCodCode(code);
            checkcode.setCodUsed(Constants.COD_USED_NO);
            checkcode.setCodSendTime(new Date());
            checkcodeService.insert(checkcode);
        }

    }

    //一信通短信通道
    private void sendMsgByUMS(String mobile, Integer codType) {
        logger.info("一信通短信通道,发送短信类型{}", codType);
        String code;
        // 开发模式验证码使用默认验证码
        if (Constants.MODE_TYPE_DEV.equals(Constants.MODE_TYPE)) {
            code = SmsConstants.DEFAULT_VERIFICATION_CODE_6;
            logger.debug("开发环境请使用默认验证码{}验证", code);
        } else {
            code = (int) ((Math.random() * 9 + 1) * 100000) + "";
        }
        String content = propertieUtil.getPropertie("TONGGUANG_SMS_CONTENT");
        content = MessageFormat.format(content, code, "通莞金服", ",");
        boolean sendResult = true;
        // 非开发模式才发送短信验证码
        if (!Constants.MODE_TYPE_DEV.equals(Constants.MODE_TYPE)) {
            int res = checkcodeService.getDifftimeByNow(mobile);
            logger.info("一信通短信通道(时间差：秒){}", res);
            if (res >= 60) {
                boolean timesLimit = checkcodeService.getCodIdByNowAndLimitCount(mobile, 4, 1);
                if (!timesLimit) {
                    boolean timesLimit2 = checkcodeService.getCodIdByNowAndLimitCount(mobile, 9, 24);
                    if (!timesLimit2) {
                        sendResult = SMSUtil.getInstance().sendMsgUMS(mobile, content);
                    } else {
                        logger.error("一信通短信通道,超过一天允许数。{}", mobile);
                        throw new BusinessException("您在一天之内获取验证码已经超过允许次数。");
                    }
                } else {
                    logger.error("一信通短信通道,超过一小时允许数。{}", mobile);
                    throw new BusinessException("您在一小时之内获取验证码已经超过允许次数。");
                }
            } else {
                throw new BusinessException("请勿频繁操作，" + (60 - res) + "秒后再获取验证码。");
            }
        }

        if (sendResult) {
            Checkcode checkcode = new Checkcode();
            checkcode.setCodType(codType);
            checkcode.setCodMobile(mobile);
            checkcode.setCodCode(code);
            checkcode.setCodUsed(Constants.COD_USED_NO);
            checkcode.setCodSendTime(new Date());
            checkcodeService.insert(checkcode);
        }
    }

    /**
     * 主营类目
     *
     * @return
     */
    @Override
    public List<BusinessKind> getKind() {
        return businessKindMapper.selectAll();
    }
}
